#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <stdlib.h>
#include <sys/wait.h>

#define NUM 1024
#define SplitNum 64
char Linestr[NUM];  //用于存储输入的字符串
char* Splitstr[SplitNum];  //指针数组：每个指针指向分割出来的字符串

int main()
{
    while(1){
    //输出提示符
    printf("用户名@主机名:当前路径$ ");
    
    //获取用户输入
    char* str=fgets(Linestr,sizeof(Linestr)-1,stdin);  //输入中末尾含有"\n"，故输出后会换行
    assert(str!=NULL);
    Linestr[strlen(Linestr)-1]=0;

    //分隔整个字符串成一个个的字符串
    Splitstr[0]=strtok(Linestr," ");  //strtok函数在第一次调用时第一个参数需要传入一个字符串，而后续只需要传入NULL告诉strtok从继续从上次返回的位置继续切割
    int i=1;
    if(strcmp(Splitstr[0],"ls")==0)  //注意c语言中不能用==来比较字符串内容，c语言的字符串中==将用于比较两个字符串的指针地址是否相同
    {
        Splitstr[i++]="--color=auto";
    }
    while(Splitstr[i++]=strtok(NULL," "));  //当最后无字符串可以切割时将返回NULL并赋给最后一个指针数组
    //如果输入的是cd命令则不需要创建子进程，如果子进程中执行了那么父进程将不会改变
    //像这种不需要子进程来执行而是让shell自己执行的命令成为内建命令
    if(Splitstr[0]!=NULL&&strcmp(Splitstr[0],"cd")==0&&Splitstr[1]!=NULL){
        chdir(Splitstr[1]);    
        continue;
    }    
    //使用execvp进行进程替换,即在环境变量中寻找并输出输入的命令
    pid_t ret=fork();
    assert(ret!=-1);
    if(ret==0){
        //child
        execvp(Splitstr[0],Splitstr);
        exit(1);
    }
    waitpid(ret,NULL,0);
    }
    /*for(int i=0;Splitstr[i];i++){
        printf("Splitstr[%d]:%s\n",i,Splitstr[i]);
    }*/
    //printf("str:%s\n",str);
    //printf("sizeof(Linestr):%d\n",sizeof(Linestr));
    return 0;
}

